﻿using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using NailsFramework.IoC;
using CID.Execution.Support.PackageRegistration;
using CID.Domain.Development;
using NailsFramework.Persistence;
using CID.Domain.Infrastructure;
using CID.Execution.Controller.Exceptions;

namespace CID.Execution.Controller.Tests.PackageRegistration
{
    [TestFixture]
    class PackageRegistratorTests : BaseControllerTests
    {
        private static readonly byte[] PackageContent = new byte[] { 1, 2, 3 };
        private const string PackageComments = "This is the package";
        private const int InvalidId = -1;
        private const string InvalidName = "";

        private IComponent Component;
        private IVersion Version;
        private IPackageType PackageType; 

        [Inject]
        public IPackageRegistrator PackageRegistrator { private get; set; }
        [Inject]
        public IBag<Version> Versions { private get; set; }

        public override void SetUp()
        {
            base.SetUp();
            
            Component = DevelopmentData.Components[0];
            Version = DevelopmentData.Components[0].Versions.First();
            PackageType = InfrastructureData.PackageType; 
        }

        #region RegisterPackage (by IDs)
        [Test]
        public void RegisterPackageByIds_ValidParameters_PackageShouldBeRegistered()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, PackageType.Id, UsersData.Operator.Id, PackageContent, PackageComments);

            var package = Versions.GetById(Version.Id).ActivePackage;

            Assert.IsNotNull(package);
            Assert.AreEqual(PackageType.Id, package.Type.Id);
            Assert.AreEqual(PackageContent, package.Content);
            Assert.AreEqual(PackageComments, package.Comment);
        }

        [Test, ExpectedException(typeof(InvalidPackageRegistrationException))]
        public void RegisterPackageByIds_InvalidComponent_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(InvalidId, Version.Id, PackageType.Id, UsersData.Operator.Id, PackageContent, PackageComments);
        }

        [Test, ExpectedException(typeof(InvalidPackageRegistrationException))]
        public void RegisterPackageByIds_InvalidVersion_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Id, InvalidId, PackageType.Id, UsersData.Operator.Id, PackageContent, PackageComments);
        }

        [Test, ExpectedException(typeof(InvalidPackageRegistrationException))]
        public void RegisterPackageByIds_InvalidPackageType_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, InvalidId, UsersData.Operator.Id, PackageContent, PackageComments);
        }

        [Test, ExpectedException(typeof(InvalidPackageRegistrationException))]
        public void RegisterPackageByIds_InvalidResponsible_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, PackageType.Id, InvalidId, PackageContent, PackageComments);
        }
        #endregion

        #region RegisterPackage (by Names)
        [Test]
        public void RegisterPackageByNames_ValidParameters_PackageShouldBeRegistered()
        {
            PackageRegistrator.RegisterPackage(Component.Name, Version.Name, PackageType.Name, UsersData.Operator.UserName, PackageContent, PackageComments);

            var package = Versions.GetById(Version.Id).ActivePackage;

            Assert.IsNotNull(package);
            Assert.AreEqual(PackageType.Id, package.Type.Id);
            Assert.AreEqual(PackageContent, package.Content);
            Assert.AreEqual(PackageComments, package.Comment);
        }

        [Test, ExpectedException(typeof(InvalidPackageRegistrationException))]
        public void RegisterPackageByNames_InvalidComponent_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(InvalidName, Version.Name, PackageType.Name, UsersData.Operator.UserName, PackageContent, PackageComments);
        }

        [Test, ExpectedException(typeof(InvalidPackageRegistrationException))]
        public void RegisterPackageByNames_InvalidVersion_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Name, InvalidName, PackageType.Name, UsersData.Operator.UserName, PackageContent, PackageComments);
        }

        [Test, ExpectedException(typeof(InvalidPackageRegistrationException))]
        public void RegisterPackageByNames_InvalidPackageType_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Name, Version.Name, InvalidName, UsersData.Operator.UserName, PackageContent, PackageComments);
        }

        [Test, ExpectedException(typeof(InvalidPackageRegistrationException))]
        public void RegisterPackageByNames_InvalidResponsible_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Name, Version.Name, PackageType.Name, InvalidName, PackageContent, PackageComments);
        }
        #endregion

        #region Authorization
        [Test]
        public void RegisterPackage_ComponentManagerUser_PackageShouldBeRegistered()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, PackageType.Id, UsersData.ComponentManager.Id, PackageContent, PackageComments);

            var package = Versions.GetById(Version.Id).ActivePackage;

            Assert.IsNotNull(package);
        }

        [Test]
        public void RegisterPackage_OperatorUser_PackageShouldBeRegistered()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, PackageType.Id, UsersData.Operator.Id, PackageContent, PackageComments);

            var package = Versions.GetById(Version.Id).ActivePackage;

            Assert.IsNotNull(package);
        }

        [Test]
        public void RegisterPackage_ReleaseManagerUser_PackageShouldBeRegistered()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, PackageType.Id, UsersData.ReleaseManager.Id, PackageContent, PackageComments);

            var package = Versions.GetById(Version.Id).ActivePackage;

            Assert.IsNotNull(package);
        }

        [Test, ExpectedException(typeof(UserActionUnauthorizedException))]
        public void RegisterPackage_ManagerUser_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, PackageType.Id, UsersData.Manager.Id, PackageContent, PackageComments);
        }

        [Test, ExpectedException(typeof(UserActionUnauthorizedException))]
        public void RegisterPackage_EnvironmentManagerUser_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, PackageType.Id, UsersData.EnvironmentManager.Id, PackageContent, PackageComments);
        }

        [Test, ExpectedException(typeof(UserActionUnauthorizedException))]
        public void RegisterPackage_DeveloperUser_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, PackageType.Id, UsersData.Developer.Id, PackageContent, PackageComments);
        }

        [Test, ExpectedException(typeof(UserActionUnauthorizedException))]
        public void RegisterPackage_RolelessUser_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, PackageType.Id, UsersData.Roleless.Id, PackageContent, PackageComments);
        }

        [Test, ExpectedException(typeof(UserActionUnauthorizedException))]
        public void RegisterPackage_ArchitectUser_ShouldThrowException()
        {
            PackageRegistrator.RegisterPackage(Component.Id, Version.Id, PackageType.Id, UsersData.Architect.Id, PackageContent, PackageComments);
        }

        #endregion
    }
}
